package cn.keniykey.mc.viewlibrary.reflection;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import javax.annotation.Nullable;

public final class ReflectionGenericClass extends ReflectionClass{
	private List<Class<?>> clazz_generics;

	public ReflectionGenericClass(Class<?> clazz) {
		super(clazz);
		this.clazz_generics = Collections.emptyList();
	}
	private void checkLinkedList() {
		if(!(this.clazz_generics instanceof LinkedList)) this.clazz_generics = new LinkedList<>();
	}
	public ReflectionGenericClass addGeneric(Class<?> clazz_generic) {
		this.checkLinkedList();
		this.clazz_generics.add(clazz_generic);
		return this;
	}
	public ReflectionGenericClass addWildcard() {
		this.checkLinkedList();
		this.clazz_generics.add(ReflectionWildcard.class);
		return this;
	}
	public ReflectionGenericClass addGenerics(Collection<Class<?>> clazz_generics) {
		this.checkLinkedList();
		this.clazz_generics.addAll(clazz_generics);
		return this;
	}
	public boolean hasGenerics() {
		return !this.clazz_generics.isEmpty();
	}
	public List<Class<?>> getGenerics() {
		return this.clazz_generics;
	}
	public ReflectionGenericClass emptyGenerics() {
		if(this.clazz_generics instanceof LinkedList) this.clazz_generics.clear();
		this.clazz_generics = Collections.emptyList();
		return this;
	}

    /**
     * 获取方法方法中的单个参数详情
     * 如果没有泛类仅返回Class，如果有泛类则返回属于LinkedList<Class>的List
     * 注：以HashMap<String,ArrayList<String>>
     * 例依次为HashMap,String,ArrayList,String
     */
	public static Object getParameterClasses(Type parametertype) {
		return getParameterClasses(parametertype, null);
	}
	private static Object getParameterClasses(Type parametertype,@Nullable LinkedList<Class<?>> linkedlist) {
		if(parametertype instanceof ParameterizedType) {
			final ParameterizedType partype = (ParameterizedType)parametertype;
			final Type[] array_types = partype.getActualTypeArguments();
			if(linkedlist == null) linkedlist = new LinkedList<>();
			final Type onlytype = partype.getRawType(); 
			if(onlytype instanceof Class<?>) linkedlist.add((Class<?>)onlytype);
			for(final Type type : array_types) {
				getParameterClasses(type, linkedlist);
			}
		}else if(parametertype instanceof Class) {//仅针对首次
			if(linkedlist != null) {
				linkedlist.add((Class<?>)parametertype);
			}else {
				return (Class<?>)parametertype;
			}
		}
		return linkedlist;
	}
}